<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */

namespace app\service\batch\kuaishou;

use app\enum\CommonEnum;
use app\enum\ConfigEnum;
use app\enum\KuaiShouEnum;
use app\model\ClientAccountModel;
use app\model\mysql\KsTimeFrameLogModel;
use app\model\mysql\KsTimeFrameTaskContentModel;
use app\model\mysql\KsTimeFrameTaskModel;
use app\service\batch\MediaInterface;
use app\service\batch\MediaService;
use app\service\client\AccountService;
use app\service\kuaishou\AdvertiserService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\facade\Db;
use think\Model;

class UnitTimeFrameService extends MediaService implements MediaInterface
{
    /**
     * @var string 批量拉取的投放时段锁
     */
    protected const BATCH_KEY = ConfigEnum::CACHE_CONFIG[KuaiShouEnum::BATCH_CONFIG_LOCK_KEY]['unit_frame_time'];

    /**
     * 获取批量拉取的快手投放时段.
     * @param KsTimeFrameTaskModel $timeFrameTaskModel
     * @return bool
     * @throws Exception
     */
    public static function uintFrameTime(KsTimeFrameTaskModel $timeFrameTaskModel): bool
    {
        $frameTaskId = $timeFrameTaskModel->getKey();
        // 获取账户信息
        $obj = AccountService::getAccountModel(0, $timeFrameTaskModel->getAttr('advertiser_id'));
        if (! $obj instanceof ClientAccountModel || ! $obj->getKey()) {
            return self::setError('账户数据不存在');
        }
        $page = 0;
        while (true) {
            $result = self::getList($timeFrameTaskModel->getAttr('advertiser_id'), ++$page);
            if ($result === false) {
                return false;
            }
            if (count($result['data']['details']) == 0) {
                break;
            }
            foreach ($result['data']['details'] as $item) {
                // 托管的不做修改
                if ($item['unit_source']) {
                    continue;
                }
                Db::startTrans();
                try {
                    // 添加投放时段内容
                    $timeFrameContentModel = self::getInfo($frameTaskId, intval($item['unit_id']));
                    if (! $timeFrameContentModel instanceof KsTimeFrameTaskContentModel || ! $timeFrameContentModel->getKey()) {
                        $timeFrameContentModel = new KsTimeFrameTaskContentModel();
                        $timeFrameContentModel->setAttrs([
                            'frame_id' => $frameTaskId,
                            'campaign_id' => $item['campaign_id'] ?? 0,
                            'unit_id' => $item['unit_id'] ?? 0,
                            'unit_name' => $item['unit_name'] ?? '',
                            'schedule_time' => $item['schedule_time'], // 投放时段
                            'status' => KsTimeFrameTaskContentModel::STATUS_WAIT,
                        ]);
                    }
                    if (! $timeFrameContentModel->save()) {
                        Db::rollback();
                        throw new Exception('保存信息出错');
                    }
                    // 添加记录日志
                    $timeFrameLog = self::addLog($timeFrameContentModel->getKey());
                    if (! $timeFrameLog) {
                        Db::rollback();
                        throw new Exception('生成出价日志失败');
                    }
                    Db::commit();
                } catch (\Exception $e) {
                    Db::rollback();
                    return self::setError($e->getMessage());
                }
            }
        }
        // 修改拉取状态
        $pullStatus = self::updatePullStatus($timeFrameTaskModel, KsTimeFrameTaskModel::PULL_SUCCESS);
        if (! $pullStatus) {
            return self::setError('更新任务状态失败');
        }
        return true;
    }

    /**
     * 设置状态.
     * @param KsTimeFrameTaskModel $timeFrameTaskModel
     * @param int $status 状态
     * @return bool
     */
    public static function setStatus(KsTimeFrameTaskModel $timeFrameTaskModel, int $status = 0): bool
    {
        $timeFrameTaskModel->setAttr('status', $status);
        if (! $timeFrameTaskModel->save()) {
            return false;
        }
        return true;
    }

    /**
     * 获取数据.
     * @param string $advertiserId 账户
     * @param int $page 页数
     * @return bool|mixed|string
     * @throws Exception
     */
    private static function getList(string $advertiserId = '', int $page = 0)
    {
        $token = AccountService::getToken(CommonEnum::KS_MEDIA, $advertiserId);
        if (! $token) {
            return self::setError('token获取失败');
        }
        $headers = [
            'Access-Token' => $token,
            'Content-Type' => 'application/json',
        ];

        $params = [
            'advertiser_id' => $advertiserId,
            'put_status_list' => [1, 2],
            'page' => $page,
            'page_size' => KuaiShouEnum::MAX_PAGE_SIZE,
        ];

        return AdvertiserService::getUnitTimeFrameList($headers, $params);
    }

    /**
     * 获取投放时段信息.
     * @param int $frameTaskId 任务id
     * @param int $unitId 广告组 ID
     * @return null|array|KsTimeFrameTaskContentModel|mixed|Model
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private static function getInfo(int $frameTaskId = 0, int $unitId = 0)
    {
        $where = [
            ['frame_id', '=', $frameTaskId],
            ['unit_id', '=', $unitId],
        ];
        return (new KsTimeFrameTaskContentModel())->where($where)->field(true)->find();
    }

    /**
     * 添加日志.
     * @param int $contentId 内容id
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private static function addLog(int $contentId = 0): bool
    {
        $where = [
            ['content_id', '=', $contentId],
        ];
        $timeFrameLogModel = (new KsTimeFrameLogModel())->where($where)->field(true)->find();
        if (! $timeFrameLogModel instanceof KsTimeFrameLogModel || ! $timeFrameLogModel->getKey()) {
            $timeFrameLogModel = new KsTimeFrameLogModel();
            $timeFrameLogModel->setAttr('content_id', $contentId);
            if (! $timeFrameLogModel->save()) {
                return false;
            }
        }
        return true;
    }

    /**
     * 修改拉取状态.
     * @param KsTimeFrameTaskModel $timeFrameTaskModel
     * @param int $pullStatus 拉取状态
     * @return bool
     */
    private static function updatePullStatus(KsTimeFrameTaskModel $timeFrameTaskModel, int $pullStatus = 0): bool
    {
        $timeFrameTaskModel->setAttr('is_pull', $pullStatus);
        if (! $timeFrameTaskModel->save()) {
            return false;
        }
        return true;
    }
}
